package com.coder.chen.slidingmenu.view;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Scroller;

public class SlidingView extends ViewGroup {

	private FrameLayout mContainer;
	private Scroller mScroller;
	private int mTouchSlop;// 用于记录允许View开始移动的最小距离

	public SlidingView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public SlidingView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public SlidingView(Context context) {
		super(context);
		init();
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		mContainer.measure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		final int width = r - l;
		final int height = b - t;
		mContainer.layout(0, 0, width, height);

	}

	private void init() {
		mContainer = new FrameLayout(getContext());
		mContainer.setBackgroundColor(0XFF000000);

		mScroller = new Scroller(getContext());

		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
		super.addView(mContainer);
	}
	
	/**
	 * 
	 * @param view
	 */
	public void setView(View view) {
		if(mContainer.getChildCount()>0){
			mContainer.removeAllViews();
		}
		mContainer.addView(view);
	}

	/**
	 * 滚动到指定位置，并立即刷新
	 */
	@Override
	public void scrollTo(int x, int y) {
		super.scrollTo(x, y);
		postInvalidate();
	}

	@Override
	public void computeScroll() {
		if (!mScroller.isFinished()) {// 未停止滚动
			if (mScroller.computeScrollOffset()) {// 动画未结束，正在移动
				int oldX = getScrollX();
				int oldY = getScrollY();

				int x = mScroller.getCurrX();
				int y = mScroller.getCurrY();

				if (oldX != x || oldY != y) {
					scrollTo(x, y);
				}
				invalidate();
			} else {// 停止滚动
				clearChildrenCache();
			}
		} else {
			clearChildrenCache();
		}
	}

	private boolean mIsBeingDragged;// 用于标识是否开始拖动动作
	private boolean mIsAlreadySetViewState = true;// 是否已经设置View
	private float mLastMotionX;
	private float mLastMotionY;

	/**
	 * 用于拦截所有的触摸时间
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {

		final int action = ev.getAction();
		final float x = ev.getX();
		final float y = ev.getY();

		switch (action) {
		case MotionEvent.ACTION_DOWN:
			mIsAlreadySetViewState = false;

			// 记录初始的x、y坐标
			mLastMotionX = x;
			mLastMotionY = y;

			mIsBeingDragged = false;
			break;

		case MotionEvent.ACTION_MOVE:
			// 获取水平和竖直位移
			final float dx = x - mLastMotionX;
			final float dy = y - mLastMotionY;
			// 获取水平和竖直位移的绝对值
			final float xDiff = Math.abs(dx);
			final float yDiff = Math.abs(dy);

			if (xDiff > mTouchSlop && xDiff > yDiff) {// 如果水平方向位移>竖直方向位移，并且水平方向位移满足最小值的要求
				mIsBeingDragged = true;// 标识开始拖动操作
				mLastMotionX = x;// 记录最后的x点坐标

			}
			break;
		}

		return mIsBeingDragged;
	}

	/************************************************************/

	private VelocityTracker mVelocityTracker;// 速率追踪器
	private static final int SNAP_VELOCITY = 1000;

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(event);

		final int action = event.getAction();
		final float x = event.getX();
		final float y = event.getY();

		switch (action) {
		case MotionEvent.ACTION_DOWN:

			if (!mScroller.isFinished()) {// 如果Scroller未停止滚动
				mScroller.abortAnimation();// 停止动画，并将Scroller移动到最终的坐标点
			}
			mLastMotionX = x;
			mLastMotionY = y;

			// 当主界面已经向右滚动了一定距离(左边栏宽度)，则返回false，不进行Move操作
			if (getScrollX() == -getMenuViewWidth()
					&& mLastMotionX < getMenuViewWidth()) {
				return false;
			}

			// 当主界面已经向左滚动了一定的距离(右边栏宽度)，则返回false，不进行Move操作
			if (getScrollX() == getDetailViewWidth()
					&& mLastMotionX > getMenuViewWidth()) {// TODO 确定右边界的宽度有待修改
				return false;
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (mIsBeingDragged) {
				enableChildrenCache();
				final float deltaX = mLastMotionX - x;// 横坐标的位移
				mLastMotionX = x;
				float oldScrollX = getScrollX();
				float scrollX = oldScrollX + deltaX;

				if (deltaX < 0 && oldScrollX < 0) {// delta<0，向右滑动；oldScrollX<0，向右滑动；显示左边栏
					// Bound用于给scrollX赋值
					final float leftBound = 0;
					final float rightBound = -getMenuViewWidth();
					if (scrollX > leftBound) {// 如果目标坐标超出了左边界
						scrollX = leftBound;// 将目标坐标设置为左边界
					} else if (scrollX < rightBound) {// 如果目标坐标超出了右边界
						scrollX = rightBound;
					}
				} else if (deltaX > 0 && oldScrollX > 0) {// delta>0，向左滑动；oldScroll>0，向左滑动；显示右边栏
					final float leftBound = 0;
					final float rightBound = getDetailViewWidth();
					if (scrollX < leftBound) {
						scrollX = leftBound;
					} else if (scrollX > rightBound) {
						scrollX = rightBound;
					}
				}

				scrollTo((int) scrollX, getScrollY());

				if (scrollX > 0) {// 向左拖动，显示右边栏
					mMenuView.setVisibility(View.GONE);
					mMenuView.clearFocus();

					mDetailView.setVisibility(View.VISIBLE);
					mDetailView.requestFocus();
				} else {// 向右拖动，显示左边栏
					mMenuView.setVisibility(View.VISIBLE);
					mMenuView.requestFocus();

					mDetailView.setVisibility(View.GONE);
					mDetailView.clearFocus();
				}
			}
			break;
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
			if (mIsBeingDragged) {
				final VelocityTracker velocityTracker = mVelocityTracker;
				velocityTracker.computeCurrentVelocity(1000);
				int velocityX = (int) velocityTracker.getXVelocity();// 获取x轴速率
				velocityX = 0;
				int oldScrollX = getScrollX();
				int dx = 0;
				if (oldScrollX < 0) {// 右移，显示左边栏
					if (oldScrollX < -getMenuViewWidth() / 2
							|| velocityX > SNAP_VELOCITY) {
						// 当右移超过一半或者速率满足时，则显示左边栏
						dx = -getMenuViewWidth() - oldScrollX;// 剩余需要移动的距离
						if (mOnScrollOpenListener != null) {
							mOnScrollOpenListener.onScrollOpen(this);
						}
					} else if (oldScrollX >= -getMenuViewWidth() / 2
							|| velocityX < -SNAP_VELOCITY) {
						// 当右移小于一半，或者速率(负向，左移)满足时，则关闭左边栏
						dx = -oldScrollX;// 根据原先滑动的距离滑动回去
						if (mOnScrollCloseListener != null) {
							mOnScrollCloseListener.onScrollClose(this);
						}
					}
				} else {// 左移，显示右边栏
					if (oldScrollX > getDetailViewWidth() / 2
							|| velocityX < -SNAP_VELOCITY) {// 左移超过一半，或者速率满足
						// 右边栏打开
						dx = getDetailViewWidth() - oldScrollX;// 剩余需要滚动的距离
						if (mOnScrollOpenListener != null) {
							mOnScrollOpenListener.onScrollOpen(this);
						}
					} else if (oldScrollX <= getDetailViewWidth() / 2
							|| velocityX > SNAP_VELOCITY) {// 左移未超过一半，或者速率(正向，右移)满足时，则关闭右边栏
						// 右边栏关闭
						dx = -oldScrollX;// 根据原先滑动的距离滑动回去
						if (mOnScrollCloseListener != null) {
							mOnScrollCloseListener.onScrollClose(this);
						}
					}
				}
				smoothScrollTo(dx);
				clearChildrenCache();
			}

			break;
		}

		// 释放速率追踪器
		if (mVelocityTracker != null) {
			mVelocityTracker.recycle();
			mVelocityTracker = null;
		}

		return super.onTouchEvent(event);
	}

	/**
	 * 平缓地滑动到指定位置
	 * 
	 * @param dx
	 */
	private void smoothScrollTo(int dx) {
		int duration = 500;
		int oldScrollX = getScrollX();
		mScroller.startScroll(oldScrollX, getScrollY(), dx, getScrollY(),
				duration);
		invalidate();

	}

	/************************************************************/

	private View mMenuView;
	private View mDetailView;

	public View getMenuView() {
		return mMenuView;
	}

	public void setMenuView(View mMenuView) {
		this.mMenuView = mMenuView;
	}

	public View getDetailView() {
		return mDetailView;
	}

	public void setDetailView(View mDetailView) {
		this.mDetailView = mDetailView;
	}

	/**
	 * 获取左边栏菜单的宽度
	 * 
	 * @return
	 */
	private int getMenuViewWidth() {
		if (mMenuView == null) {
			return 0;
		}
		return mMenuView.getWidth();
	}

	/**
	 * 获取右边栏 详情 的宽度
	 * 
	 * @return
	 */
	private int getDetailViewWidth() {
		if (mDetailView == null) {
			return 0;
		}
		return mDetailView.getWidth();
	}

	/**
	 * 打开子View的缓存
	 */
	private void enableChildrenCache() {
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			final View layout = (View) getChildAt(i);
			layout.setDrawingCacheEnabled(true);
		}

	}

	/**
	 * 清空所有子View的缓存
	 */
	private void clearChildrenCache() {
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			final View layout = (View) getChildAt(i);
			layout.setDrawingCacheEnabled(false);
		}
	}

	/*************************************************************/

	private OnScrollOpenListener mOnScrollOpenListener = null;
	private OnScrollCloseListener mOnScrollCloseListener = null;
	
	public void setOnScrollOpenListener(OnScrollOpenListener listener){
		this.mOnScrollOpenListener = listener;
	}
	
	public void setOnScrollCloseListener(OnScrollCloseListener listener){
		this.mOnScrollCloseListener = listener;
	}
	
	/**
	 * 侧边栏打开的监听
	 * 
	 * @author chenchong
	 * 
	 */
	public interface OnScrollOpenListener {
		public void onScrollOpen(SlidingView slidingView);
	}

	/**
	 * 侧边栏关闭的监听
	 * 
	 * @author chenchong
	 * 
	 */
	public interface OnScrollCloseListener {
		public void onScrollClose(SlidingView slidingView);
	}

	/****************************************************************/

	/**
	 * 打开（关闭）左边栏
	 */
	public void showLeftView() {
		mMenuView.setVisibility(View.VISIBLE);
		mMenuView.requestFocus();
		mDetailView.setVisibility(View.GONE);
		mDetailView.clearFocus();

		int menuWidth = mMenuView.getWidth();
		int oldScrollX = getScrollX();
		if (oldScrollX == 0) {// 未打开
			smoothScrollTo(-menuWidth);
		} else if (oldScrollX == -menuWidth) {// 已打开
			smoothScrollTo(menuWidth);
		}
	}

	/**
	 * 打开（关闭）右边栏
	 */
	public void showRightView() {
		mMenuView.setVisibility(View.GONE);
		mMenuView.clearFocus();
		mDetailView.setVisibility(View.VISIBLE);
		mDetailView.requestFocus();

		int mentWidth = mDetailView.getWidth();
		int oldScrollX = getScrollX();
		if (oldScrollX == 0) {// 未打开
			smoothScrollTo(mentWidth);
		} else if (oldScrollX == mentWidth) {// 已打开
			smoothScrollTo(-mentWidth);
		}
	}

	/**
	 * 显示中间页面
	 */
	public void showCenterView() {
		// TODO 用于判断打开页面的menuWidth，有待修改
		int menuWidth = mDetailView.getWidth();
		int oldScrollX = getScrollX();
		if (oldScrollX == menuWidth) {
			showRightView();
		} else if (oldScrollX == -menuWidth) {
			showLeftView();
		}

		if (mOnScrollCloseListener != null) {
			mOnScrollCloseListener.onScrollClose(this);
		}

	}

}
